﻿namespace EFS.Common.UI.Controls
{
	public class ComboBoxEnumHelper<TEnum> where TEnum : struct, System.IConvertible, System.IComparable, System.IFormattable
	{
		#region Inner Classes
		/// Class ComboBoxItem
		public class ComboBoxItem
		{
			/// Constructor
			public ComboBoxItem(TEnum? value)
			{
				// reset
				Text = null;
				Value = null;

				// test value
				if (value.HasValue)
				{
					// create string enum
					EFS.Common.StringEnum stringEnum = new EFS.Common.StringEnum(typeof(TEnum));

					// set
					Text = stringEnum.GetStringValue(value.ToString());
					Value = value;
				}
			}

			/// Property Text: Get, Set
			public System.String Text { get; private set; }

			/// Property Value: Get, Set
			public TEnum? Value { get; private set; }

			/// Property HasValue: Get
			public System.Boolean HasValue
			{
				get
				{
					return Value.HasValue;
				}
			}

			/// ToString
			public override System.String ToString()
			{
				// has value
				if (!HasValue)
				{
					if (EFS.Common.Verify.String(Text))
					{
						return Text;
					}
					return " ";
				}
				else
				{
					// 
					if (EFS.Common.Verify.String(Text))
					{
						return Text;
					}
					return Value.Value.ToString();
				}
			}
		}
		#endregion

		#region Locals
		/// combo box
		private System.Windows.Controls.ComboBox comboBox = null;

		/// itemsCached
		private System.Collections.Generic.List<ComboBoxItem> itemsCached = null;
		#endregion

		#region Constructors
		/// Explicit
		public ComboBoxEnumHelper(
			System.Windows.Controls.ComboBox comboBox)
		{
			// check
			EFS.Common.Verify.Reference(comboBox, "comboBox");

			// check enum predicate
			CheckTEnumTypePredicate();

			// set
			this.comboBox = comboBox;
		}
		#endregion

		#region Properties
		/// Property HasEmpty: Get
		public System.Boolean HasEmpty
		{
			get
			{
				if (Items.Length > 0 && !Items[0].HasValue)
				{
					return true;
				}
				return false;
			}
		}

		/// Property Items: Get
		public ComboBoxItem[] Items
		{
			get
			{
				if (null == itemsCached)
				{
					itemsCached = new System.Collections.Generic.List<ComboBoxItem>();
					foreach (ComboBoxItem item in this.comboBox.Items)
					{
						itemsCached.Add(item);
					}
				}
				return itemsCached.ToArray();
			}
		}

		/// Property SelectedValue: Get, Set
		public TEnum? SelectedValue
		{
			get
			{
				ComboBoxItem selectedItem = SelectedItem;
				if (null != selectedItem)
				{
					return selectedItem.Value;
				}
				return null;
			}
			set
			{
				if (!value.HasValue)
				{
					if (HasEmpty)
					{
						SelectedIndex = 0;
					}
					else
					{
						SelectedIndex = -1;
					}
				}
				else
				{
					for (System.Int32 i = 0; i < Items.Length; ++i)
					{
						if (Items[i].Value.HasValue && Items[i].Value.Value.Equals(value.Value))
						{
							SelectedIndex = i;
							break;
						}
					}
				}
			}
		}

		/// Property SelectedItem: Get, Set
		public ComboBoxItem SelectedItem
		{
			get
			{
				return this.comboBox.SelectedItem as ComboBoxItem;
			}
			set
			{
				this.comboBox.SelectedItem = value;
			}
		}

		/// Property SelectedIndex: Get, Set
		public System.Int32 SelectedIndex
		{
			get
			{
				return this.comboBox.SelectedIndex;
			}
			set
			{
				this.comboBox.SelectedIndex = value;
			}
		}

		#endregion

		#region Utilities
		/// CheckTEnumTypePredicate
		private void CheckTEnumTypePredicate()
		{
			if (!typeof(TEnum).IsEnum)
			{
				throw new System.NotSupportedException("TEnum must be an enumerated type");
			}
		}
		#endregion

		#region Combo Manipulation
		/// ClearSelection
		public void ClearSelection()
		{
			if (HasEmpty)
			{
				SelectedIndex = 0;
			}
			else
			{
				SelectedIndex = -1;
			}
		}

		/// Clear
		public void Clear()
		{
			// clear itemsCached
			itemsCached = null;
			comboBox.Items.Clear();
		}

		/// Populate
		public void Populate(System.Boolean addEmpty = false)
		{
			// clear itemsCached
			Clear();

			// add empty
			ComboBoxItem item = null;
			if (addEmpty)
			{
				item = new ComboBoxItem(null);
				this.comboBox.Items.Add(item);
			}

			// cicle all
			foreach (TEnum value in EFS.Common.Values.Enum<TEnum>.EnumValues)
			{
				item = new ComboBoxItem(value);
				this.comboBox.Items.Add(item);
			}
		}

		#endregion
	}

}